#include "bhxjwavesin.h"

BHXJWaveSin::BHXJWaveSin(QWidget *parent) : QOpenGLWidget(parent)
{
    QSurfaceFormat surfaceFormat(this->format());
    surfaceFormat.setDepthBufferSize(0);   //不使用深度缓存
    surfaceFormat.setStencilBufferSize(0); //
    surfaceFormat.setSamples(4);
    setFormat(surfaceFormat);

    void (BHXJWaveSin::*fun)()=&BHXJWaveSin::update;
    connect(this,&BHXJWaveSin::Refrush,this,fun,Qt::QueuedConnection);
    connect(this,&BHXJWaveSin::RefrushMask,this,&BHXJWaveSin::updateMask,Qt::QueuedConnection);

    timer=new QTimer(this);
    timer->setInterval(20);
    connect(timer,&QTimer::timeout,this,&BHXJWaveSin::timeoutfun);


    timer->start();
}
void BHXJWaveSin::paintEvent(QPaintEvent *event)
{
    if(this->width()<=0||this->height()<=0)
        return;
    if(this->_BeEllipse)
    {    QRegion qr(0,0,this->width(),this->height(),QRegion::Ellipse);
        this->setMask(qr);
    }
    else
    {
        this->clearMask();
    }
    this->updateSinY();
    QOpenGLWidget::paintEvent(event);
    QPainter painter;
    painter.begin(this);
    painter.setRenderHints(QPainter::Antialiasing);

    painter.setPen(Qt::NoPen);
    painter.setBrush(this->palette().background());
    painter.drawRect(0,0,this->width(),this->height());

    double startx=0;
    double endx=this->width();
    double endy=this->height();
    double starty=endy*(1-_Value);

    double interval=endx/(_Samples*_WaveDensity);
    int step=static_cast<int>(_Samples*_WaveDensity)+3;
    int samples=static_cast<int>(_Samples);

    QPainterPath path1;
    QColor color1(_WaveColor);
    color1.setAlpha(150);
    path1.moveTo(startx,endy);

    QPainterPath path2;
    QColor color2(_WaveColor);
    color2.setAlpha(150);
    path2.moveTo(startx,endy);

    //起始相位索引
    int temp=static_cast<int>(offset);
    //相位差
    int phase=static_cast<int>(samples*_PhaseDifference+0.5);
    //偏移相位不是整数时调整startx来实现小数相位偏移
    startx=-(offset-temp)*interval;
    startx=startx>0?startx-interval:startx;

    {
        lock_guard<mutex> lock(this->sinYlock);
        for(int i=0;i<step;++i)
        {
            int index1=(i+temp)%samples;
            index1=index1<0?index1+samples:index1;
            path1.lineTo(startx +i*interval,starty- endy*0.5*_WaveHeight*sinY[index1]);

            int index2=(i+temp+phase)%samples;
            index2=index2<0?index2+samples:index2;
            path2.lineTo(startx +i*interval,starty- endy*0.5*_WaveHeight*sinY[index2]);
        }
    }
    path1.lineTo(endx,endy);
    path2.lineTo(endx,endy);
    painter.setPen(Qt::NoPen);
    painter.setBrush(color1);
    painter.drawPath(path1);
    painter.setBrush(color2);
    painter.drawPath(path2);
    if(this->BeEllipse())
    {
        painter.setBrush(Qt::NoBrush);
        painter.setPen(QPen(_FrameColor,2));
        painter.drawEllipse(0,0,this->width(),this->height());
    }
    QFont mfont(this->font());
    mfont.setPointSizeF((endx>endy?endy:endx)/6);
    QFontMetrics metric(mfont);
    painter.setPen(QPen(this->palette().text().color()));
    QString str=QString::number(static_cast<int>(_Value*100.+0.01));
    str.append("%");
    QRect boundingRect = metric.boundingRect(str);
    painter.setFont(mfont);
    painter.drawText(QPointF(this->width()/2-boundingRect.width()/2,endy*0.5+boundingRect.height()*0.3),str);
    painter.end();
}

void BHXJWaveSin::timeoutfun()
{
    this->offset+=_Samples*_WaveDensity*_Speed*0.02;
    int n=static_cast<int>(this->offset/_Samples);
    this->offset-=n*static_cast<int>(_Samples);
    this->update();
}
void BHXJWaveSin::updateSinY()
{
    if(!this->sinYFlag)
    {
        return;
    }
    lock_guard<mutex> lock(this->sinYlock);
    this->sinYFlag=false;
    this->sinY.clear();
    for(uint i=0;i<_Samples;++i)
    {
        double x= (static_cast<double>(i)/_Samples)* M_PI*2;
        double y=qSin(x);
        this->sinY.push_back(y);
    }
}
void BHXJWaveSin::updateMask()
{
    if(this->_BeEllipse)
    {    QRegion qr(0,0,this->width(),this->height(),QRegion::Ellipse);
        this->setMask(qr);
    }
    else
    {
        this->clearMask();
    }
}
